package com.swak.vertx.invoker;

import java.lang.reflect.Method;

import org.springframework.util.Assert;

import com.swak.asm.MethodCache;
import com.swak.asm.MethodCache.ClassMeta;
import com.swak.asm.MethodCache.MethodMeta;
import com.swak.asm.Wrapper;
import com.swak.vertx.transport.script.Script;

/**
 * 通用的执行类
 * 
 * @author lifeng
 */
public class GenericFluxInvoker implements FluxInvoker {

	private final Object service;
	private final Class<?> type;
	private final String address;
	private final ClassMeta classMeta;
	private final Wrapper wrapper;

	public GenericFluxInvoker(Object service) {
		Assert.isTrue(service != null, "Type Can Not Be Null!");
		this.service = service;
		this.type = service.getClass();
		this.address = this.getAddress(this.type, null);
		this.classMeta = MethodCache.set(this.type);
		this.wrapper = Wrapper.getWrapper(this.type);
	}

	/**
	 * 发起远程访问
	 * 
	 * @param method
	 * @param args
	 * @return
	 * @throws Throwable
	 */
	public Object doInvoke(Method method, Object[] args) throws Throwable {
		MethodMeta meta = this.classMeta.lookup(method);
		if (meta == null || meta.isLocal()) {
			return wrapper.invokeMethod(service, meta.getMethodDesc(), args);
		}
		return this.doRemoteInvoke(address, meta, args);
	}

	/**
	 * 远程执行脚本
	 * 
	 * @param script
	 * @return
	 * @throws Throwable
	 */
	public Object doInvoke(Script script) throws Throwable {
		return this.doRemoteInvoke(address, script);
	}
}